package foo.shaketest;

import java.util.HashMap;
import java.util.TimerTask;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;


import ugla.shake.SHAKEConstants;
import ugla.shake.SHAKEDevice;
import ugla.shake.bluetooth.SHAKEAndroidBluetooth;

public class SHAKETest extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // create a new SHAKEDevice instance using the Android Bluetooth class for connections
        sd = new SHAKEDevice(new SHAKEAndroidBluetooth());
        
        connectButton = (Button) findViewById(R.id.ConnectButton);
        disconnectButton = (Button) findViewById(R.id.DisconnectButton);
        scanButton = (Button) findViewById(R.id.BTDiscoveryButton);
        
        accDisplay = (SensorDisplay) findViewById(R.id.AccDisplay);
        magDisplay = (SensorDisplay) findViewById(R.id.MagDisplay);
        gyroDisplay = (SensorDisplay) findViewById(R.id.GyroDisplay);
        
        // timer task to update the UI with SHAKE sensor data
        handler.postDelayed(new UpdateSHAKE(), 50);
        
        // turn on Bluetooth if necessary
        bta = BluetoothAdapter.getDefaultAdapter();
        int btstatus = bta.getState();
        if(btstatus == bta.STATE_OFF || btstatus == bta.STATE_TURNING_OFF)
        	bta.enable();
        
        // register an intent filter for receiving Bluetooth discovery events
        devices = new HashMap<String, String>();
        IntentFilter intfil = new IntentFilter();
        intfil.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        intfil.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intfil.addAction(BluetoothDevice.ACTION_FOUND);
        this.registerReceiver(new BTListener(), intfil);
        
        // connect button handler; this connects to a selected SHAKE using its hardware address
        // and then turns all the sensor power on, switches it to binary data output, and then sets
        // a 30Hz sample rate for the accelerometer, magnetometer and gyroscope outputs. 
        connectButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				if(!connected) {
					connected = sd.connect(selected_device_address);
					if(connected) {
						sd.writePowerState(0xFF);
						sd.writeDataFormat(0x02);
						sd.writeSampleRate(SHAKEConstants.SHAKE_SENSOR_ACC, 30);
						sd.writeSampleRate(SHAKEConstants.SHAKE_SENSOR_MAG, 30);
						sd.writeSampleRate(SHAKEConstants.SHAKE_SENSOR_GYRO, 30);
						connectButton.setEnabled(false);
						scanButton.setEnabled(false);
						disconnectButton.setEnabled(true);
					}
				}
			}
		});
        
        disconnectButton.setOnClickListener(new View.OnClickListener() {
        	public void onClick(View v) {
        		if(connected) 
        			sd.close();
        		connected = false;
        		connectButton.setEnabled(true);
				scanButton.setEnabled(true);
				disconnectButton.setEnabled(false);
        	}
        });
        
        scanButton.setOnClickListener(new View.OnClickListener() {
        	public void onClick(View v) {
        		bta.getDefaultAdapter().startDiscovery();
        		scanButton.setEnabled(false);
        	}
        });
        
    }
    
    protected Dialog onCreateDialog(int id) {
    	switch(id) {
    		// this dialog displays a list of Bluetooth devices by name and allows you to pick one to connect to
    		case BT_DEVICE_SELECT_DIALOG: {
    			AlertDialog.Builder builder = new AlertDialog.Builder(this);
    			builder.setTitle("Select device");
    			final CharSequence[] items = new CharSequence[devices.size()];
    			builder.setItems(devices.keySet().toArray(items), new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						connectButton.setText("Connect " + items[which]);
						selected_device_address = devices.get(items[which]);
						connectButton.setEnabled(true);
					}
    			
    			});
    			return builder.create();
    		}
    		default:
    			break;
    	}
    	return null;
    }
    
    private void displayDeviceSelectionDialog() {
    	showDialog(BT_DEVICE_SELECT_DIALOG);
    }
    
    // this task reads the latest sensor data from the SHAKE and updates the UI
    private class UpdateSHAKE extends TimerTask {
		@Override
		public void run() {
			if(connected) {
				int[] acc = sd.acc();
				int[] mag = sd.mag();
				int[] gyro = sd.gyro();
			
				accDisplay.updateData(acc);
				magDisplay.updateData(mag);
				gyroDisplay.updateData(gyro);
			}
			handler.postDelayed(this, 50);
		}
    	
    };
    
    // class which receives Bluetooth discovery events
    private class BTListener extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			if(intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
				 
			} else if(intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
				scanButton.setEnabled(true);
				// trigger the device selection dialog
				new BTScanCompleteTask().execute(null);
			} else if(intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
				// device found, store the device name and address for later use
				BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				devices.put(device.getName(), device.getAddress());
			}
		}
    };
    
    // This task is used to display a dialog listing Bluetooth devices found when the scan has completed
    private class BTScanCompleteTask extends AsyncTask<Void, Void, Void> {

		@Override
		protected Void doInBackground(Void... params) {
			
			
			return null;
		}
		
		protected void onPostExecute(Void result) {
			displayDeviceSelectionDialog();
		}
    };
    
    private static final int BT_DEVICE_SELECT_DIALOG = 1;
    
    private SensorDisplay accDisplay = null;
    private SensorDisplay magDisplay = null;
    private SensorDisplay gyroDisplay = null;
    private Handler handler = new Handler();
    private Button connectButton = null;
    private Button disconnectButton = null;
    private Button scanButton = null;
    private SHAKEDevice sd = null;
    private boolean connected = false;
    private BluetoothAdapter bta = null;
    private HashMap<String, String> devices = null;
    private String selected_device_address = null;
}